﻿using System;

namespace Gmantis.Controls.DataGrid
{
    public class DataGridSelectionManager
    {
        // Fields
        private object _latestSelectedObject;

        // Methods
        internal DataGridSelectionManager(DataGridModel model, DataGridSelectionMode selectionMode)
        {
            EventHandler<DataGridSelectionChangedEventArgs> handler = null;
            EventHandler<DataGridSelectionChangedEventArgs> handler2 = null;
            this.Model = model;
            this.Selection = new DataGridSelection(model);
            if (handler == null)
            {
                handler = (s, e) => this.Model.OnSelectionChanged(e);
            }
            this.Selection.SelectionChanged += handler;
            if (handler2 == null)
            {
                handler2 = (s, e) => this.Model.OnSelectionChanging(e);
            }
            this.Selection.SelectionChanging += handler2;
            this.Selection.Mode = selectionMode;
        }

        public void Clear()
        {
            this.Selection.Clear();
        }

        internal void ReleaseRow(DataGridRow row)
        {
            if (this.SelectedRows.Contains(row))
            {
                this.Selection.Clear(true);
            }
            if (this._latestSelectedObject == row)
            {
                this._latestSelectedObject = null;
            }
        }

        public void Select(DataGridCell cell)
        {
            this.Select(cell, KeyboardUtil.Shift, KeyboardUtil.Ctrl);
        }

        public void Select(DataGridColumn column)
        {
            this.Select(column, column, KeyboardUtil.Shift, KeyboardUtil.Ctrl);
        }

        public void Select(DataGridRow row)
        {
            this.Select(row, KeyboardUtil.Shift, KeyboardUtil.Ctrl);
        }

        public void Select(DataGridRow fromRow, DataGridRow toRow)
        {
            this.Select(fromRow, toRow, KeyboardUtil.Shift, KeyboardUtil.Ctrl);
        }

        public void Select(DataGridCell cell, bool shift, bool ctrl)
        {
            this.Select(cell, cell, shift, ctrl);
        }

        public void Select(DataGridRow row, bool shift, bool ctrl)
        {
            this.Select(row, row, shift, ctrl);
        }

        public void Select(DataGridCell fromCell, DataGridCell toCell, bool shift, bool ctrl)
        {
            this.Selection.BeginUpdate();
            if (shift)
            {
                if (((this._latestSelectedObject != null) && (this._latestSelectedObject is DataGridCell)) && ((this._latestSelectedObject as DataGridCell).DataGrid != null))
                {
                    fromCell = this._latestSelectedObject as DataGridCell;
                }
                if (!ctrl)
                {
                    this.Selection.Clear();
                }
                this.Selection.Add(fromCell, toCell);
            }
            else if (ctrl)
            {
                if (this.Selection.Contains(fromCell))
                {
                    this.Selection.Remove(fromCell, toCell);
                }
                else
                {
                    this.Selection.Add(fromCell, toCell);
                }
                this._latestSelectedObject = fromCell;
            }
            else
            {
                this.Selection.Clear();
                this.Selection.Add(fromCell, toCell);
                this._latestSelectedObject = fromCell;
            }
            this.Selection.EndUpdate();
        }

        public void Select(DataGridColumn fromColumn, DataGridColumn toColumn, bool shift, bool ctrl)
        {
            this.Selection.BeginUpdate();
            if (shift)
            {
                if ((shift && (this._latestSelectedObject != null)) && (((this._latestSelectedObject is DataGridCell) && ((this._latestSelectedObject as DataGridCell).DataGrid != null)) || ((this._latestSelectedObject is DataGridColumn) && ((this._latestSelectedObject as DataGridColumn).DataGrid != null))))
                {
                    fromColumn = (this._latestSelectedObject is DataGridColumn) ? ((DataGridColumn)this._latestSelectedObject) : ((DataGridCell)this._latestSelectedObject).Column;
                }
                if (!ctrl)
                {
                    this.Selection.Clear();
                }
                this.Selection.Add(fromColumn, toColumn);
            }
            else if (ctrl)
            {
                if (this.Selection.Contains(fromColumn))
                {
                    this.Selection.Remove(fromColumn, toColumn);
                }
                else
                {
                    this.Selection.Add(fromColumn, toColumn);
                }
                this._latestSelectedObject = fromColumn;
            }
            else
            {
                this.Selection.Clear();
                this.Selection.Add(fromColumn, toColumn);
                this._latestSelectedObject = fromColumn;
            }
            this.Selection.EndUpdate();
        }

        public void Select(DataGridRow fromRow, DataGridRow toRow, bool shift, bool ctrl)
        {
            this.Selection.BeginUpdate();
            if (shift)
            {
                if ((shift && (this._latestSelectedObject != null)) && (((this._latestSelectedObject is DataGridCell) && ((this._latestSelectedObject as DataGridCell).DataGrid != null)) || ((this._latestSelectedObject is DataGridRow) && ((this._latestSelectedObject as DataGridRow).DataGrid != null))))
                {
                    fromRow = (this._latestSelectedObject is DataGridRow) ? ((DataGridRow)this._latestSelectedObject) : ((DataGridCell)this._latestSelectedObject).Row;
                }
                if (!ctrl)
                {
                    this.Selection.Clear();
                }
                this.Selection.Add(fromRow, toRow);
            }
            else if (ctrl)
            {
                if (this.Selection.Contains(fromRow))
                {
                    this.Selection.Remove(fromRow, toRow);
                }
                else
                {
                    this.Selection.Add(fromRow, toRow);
                }
                this._latestSelectedObject = fromRow;
            }
            else
            {
                this.Selection.Clear();
                this.Selection.Add(fromRow, toRow);
                this._latestSelectedObject = fromRow;
            }
            this.Selection.EndUpdate();
        }

        // Properties
        internal DataGridModel Model { get; private set; }

        public DataGridSelectedItemsCollection<DataGridCell> SelectedCells
        {
            get
            {
                return this.Selection.SelectedCells;
            }
        }

        public DataGridSelectedItemsCollection<DataGridColumn> SelectedColumns
        {
            get
            {
                return this.Selection.SelectedColumns;
            }
        }

        public DataGridRow SelectedRow
        {
            get
            {
                if (this.Selection.SelectedRows.Count > 0)
                {
                    return this.Selection.SelectedRows[0];
                }
                return null;
            }
        }

        public DataGridSelectedItemsCollection<DataGridRow> SelectedRows
        {
            get
            {
                return this.Selection.SelectedRows;
            }
        }

        public DataGridSelection Selection { get; private set; }
    }
}
